package com.cdy.client.handler;

import com.cdy.client.FileDownloadClient;
import com.cdy.client.netty.NettyClient;
import com.cdy.common.command.DownloadCommand;
import com.cdy.common.domain.FileSectionEntity;
import com.cdy.common.property.CommonProperty;
import com.cdy.common.response.DownloadResponse;
import com.cdy.common.response.Response;
import com.cdy.common.uitl.FileUtil;
import com.cdy.common.uitl.MathUtil;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.nio.channels.FileChannel;
import java.util.BitSet;

import static com.cdy.client.netty.NettyClient.NETTY_CLIENT;
import static com.cdy.common.uitl.BitSetUtil.correctLong;
import static com.cdy.common.uitl.BitSetUtil.sectionFinish;


/**
 * 下载响应处理器
 * <p>
 * Created by 陈东一
 * 2019/10/20 0020 12:36
 */
@Slf4j
public class DownloadResponseHandler implements ResponseHandler {

    @Override
    public void handle(ChannelHandlerContext ctx, Response msg)  {
        DownloadCommand uploadResponse = new DownloadCommand();
        NettyClient nettyClient = ctx.channel().attr(NETTY_CLIENT).get();
        uploadResponse.setClientId(nettyClient.getCommonProperty().getClientId());
        try {
            DownloadResponse downloadResponse = (DownloadResponse) msg;

            initDownloadCommand(uploadResponse, downloadResponse);

            FileChannel fileChannel = FileDownloadClient.fileMap.get(downloadResponse.getSectionId());
            FileSectionEntity sectionEntity = FileDownloadClient.sectionMap.get(downloadResponse.getSectionId());
            BitSet bitSet = sectionEntity.getBitSet();

            long sectionSize = CommonProperty.SmallSectionLength;
            // 确定分片 在分段的位置
            int position = MathUtil.divide(correctLong(downloadResponse.getBegin() - downloadResponse.getSectionBegin()), sectionSize) - 1;

            if (!bitSet.get(position)) { //该小片段不存在则写入
                FileUtil.write(fileChannel, downloadResponse.getByteBuf().nioBuffer(), downloadResponse.getBegin());
                downloadResponse.getByteBuf().release();
                bitSet.set(position);
            }

            Boolean last = downloadResponse.getLast();
            Boolean finish = sectionFinish(position, downloadResponse.getBitBegin(), downloadResponse.getBitSize(), bitSet);
            if (finish || last) {
                //全部完成 需要去掉clientId 和 设置完成
                boolean sectionTotalFinish = bitSet.nextClearBit(0) == bitSet.length();
                if (sectionTotalFinish) {
                    sectionEntity.setClientId(null);
                    sectionEntity.setComplete(true);
                }

                FileChannel remove = FileDownloadClient.fileMap.remove(downloadResponse.getSectionId());
                if (remove != null) {
                    remove.close();
                }
            }
            write(ctx,uploadResponse);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }

    }

    /**
     * 初始化下载命令
     * @param uploadResponse
     * @param downloadResponse
     */
    private void initDownloadCommand(DownloadCommand uploadResponse, DownloadResponse downloadResponse) {
        uploadResponse.setBegin(downloadResponse.getBegin());
        uploadResponse.setBitBegin(downloadResponse.getBitBegin());
        uploadResponse.setBitSize(downloadResponse.getBitSize());
        uploadResponse.setBitTotal(downloadResponse.getBitTotal());
        uploadResponse.setSectionBegin(downloadResponse.getSectionBegin());
    }
}
